package com.hzhq.contract.service.impl;

import com.hzhq.contract.bean.dto.AttachmentDTO;
import com.hzhq.contract.bean.entity.Attachment;
import com.hzhq.contract.bean.entity.ContractStatus;
import com.hzhq.contract.convert.AttachmentConvertBasic;
import com.hzhq.contract.convert.ContractStatusConvertBasic;
import com.hzhq.contract.repo.AttachmentRepository;
import com.hzhq.contract.result.Result;
import com.hzhq.contract.service.AttachmentService;
import com.hzhq.contract.status.DefaultValue;
import com.hzhq.contract.util.ConvertUtil;
import com.hzhq.contract.util.Page2ResultUtil;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.mongodb.core.query.UpdateDefinition;
import org.springframework.data.mongodb.gridfs.GridFsTemplate;
import org.springframework.stereotype.Service;


import java.nio.file.Path;
import java.sql.ResultSet;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author hzhq
 * @create 2021/4/12 8:09 下午
 * @email hzhq1255@163.com
 */
@Service
public class AttachmentServiceImpl implements AttachmentService {

    @Autowired
    MongoTemplate mongoTemplate;

    @Autowired
    AttachmentRepository attachmentRepository;

    @Autowired
    GridFsTemplate gridFsTemplate;

    @Override
    public Page<AttachmentDTO> searchAllPageByExample(AttachmentDTO attachmentDTO, Integer currentPage, Integer pageSize) {
        Attachment attachment = AttachmentConvertBasic.INSTANCE.dtoToPo(attachmentDTO);
        attachment.setDeleted(DefaultValue.NOT_DELETED);
        Sort sort = Sort.by(Sort.Direction.DESC,"attachId");
        Pageable pageable = Page2ResultUtil.buildPageableByParam(currentPage, pageSize, sort);
        ExampleMatcher exampleMatcher = ExampleMatcher.matching()
                .withMatcher("attachName",ExampleMatcher.GenericPropertyMatchers.contains())
                .withMatcher("md5",ExampleMatcher.GenericPropertyMatchers.contains())
                .withMatcher("contentType",ExampleMatcher.GenericPropertyMatchers.contains())
                .withMatcher("path",ExampleMatcher.GenericPropertyMatchers.contains());
        return attachmentRepository.findAll(Example.of(attachment,exampleMatcher),pageable).map(AttachmentConvertBasic.INSTANCE::poToDto);
    }

    @Override
    public Page<AttachmentDTO> searchAllPageByQuery(Query query, Integer currentPage, Integer pageSize) {
        Sort sort = Sort.by(Sort.Direction.DESC,"attachId");
        Pageable pageable = Page2ResultUtil.buildPageableByParam(currentPage, pageSize, sort);
        long count = mongoTemplate.count(query,Attachment.class);
        Page<Attachment> attachments = new PageImpl<>(mongoTemplate.find(query.with(pageable),Attachment.class),pageable,count);
        return attachments.map(AttachmentConvertBasic.INSTANCE::poToDto);
    }

    @Override
    public AttachmentDTO getOneByContractIdAndMd5(String contractId, String md5) {
        Optional<Attachment> attachmentOptional = attachmentRepository.findByContractIdAndMd5AndDeleted(
                        ConvertUtil.stringToObjectId(contractId),md5,DefaultValue.NOT_DELETED);
        return attachmentOptional.map(AttachmentConvertBasic.INSTANCE::poToDto).orElse(null);
    }

    @Override
    public AttachmentDTO getOneByContractIdAndAttachId(String contractId, String attachId) {
        Optional<Attachment> attachmentOptional = attachmentRepository.findByContractIdAndAttachIdAndDeleted(ConvertUtil.stringToObjectId(contractId),ConvertUtil.stringToObjectId(attachId),DefaultValue.NOT_DELETED);
        return attachmentOptional.map(AttachmentConvertBasic.INSTANCE::poToDto).orElse(new AttachmentDTO());
    }

    @Override
    public AttachmentDTO save(AttachmentDTO attachmentDTO){
        Attachment attachment = attachmentRepository.save(AttachmentConvertBasic.INSTANCE.dtoToPo(attachmentDTO));
        return AttachmentConvertBasic.INSTANCE.poToDto(attachment);
    }

    @Override
    public String deleteByContractIdAndAttachId(String contractId, String attachId) {
        Optional<Attachment> attachmentOptional = attachmentRepository.findByContractIdAndAttachIdAndDeleted(ConvertUtil.stringToObjectId(contractId),ConvertUtil.stringToObjectId(attachId),DefaultValue.NOT_DELETED);
        if (attachmentOptional.isPresent()){
           Attachment attachment = attachmentOptional.get();
           attachment.setDeleted(DefaultValue.DELETED);
            return attachmentRepository.save(attachment).getAttachId().toString();
        }
        return null;
    }


    @Override
    public Result<Object> saveAttachment(Attachment attachment) {
        attachmentRepository.save(attachment);
        return Result.success("附件保存成功");
    }

    @Override
    public List<AttachmentDTO> saveAll(List<AttachmentDTO> attachmentDTOList) {
        List<Attachment> attachments = attachmentRepository.saveAll(attachmentDTOList.stream().map(AttachmentConvertBasic.INSTANCE::dtoToPo).collect(Collectors.toList()));
        return attachments.stream().map(AttachmentConvertBasic.INSTANCE::poToDto).collect(Collectors.toList());
    }

    @Override
    public List<Attachment> savAll(List<Attachment> attachmentList) {
        return attachmentRepository.saveAll(attachmentList);
    }


    @Override
    public Result<Object> deletedAttachment(ObjectId attachId) {
        attachmentRepository.deleteById(attachId);
        return Result.success("附件删除成功");
    }




    @Override
    public Result<Object> getPageAttachment(Integer currentPage, Integer pageSize) {
        Sort sort = Sort.by(Sort.Direction.DESC,"uploadTime");
        Pageable pageable = PageRequest.of(currentPage,pageSize,sort);
        Page<Attachment> attachmentPage = attachmentRepository.findAll(pageable);
        return Result.success(Page2ResultUtil.getPageData(attachmentPage));
    }
    
    @Override
    public List<String> deleteByIds(List<ObjectId> ids) {
        List<ObjectId> objectIds = attachmentRepository.findByAttachIdInAndDeleted(ids,DefaultValue.NOT_DELETED).stream().map(Attachment::getAttachId).collect(Collectors.toList());
        Update update = new Update().set("deleted",DefaultValue.NOT_DELETED);
        mongoTemplate.updateMulti(Query.query(Criteria.where("_id").in(objectIds)),update,Attachment.class);
        return objectIds.stream().map(ObjectId::toString).collect(Collectors.toList());

    }

    @Override
    public Page<AttachmentDTO> searchAllPages(AttachmentDTO attachmentDTO, Integer currentPage, Integer pageSize) {
        Attachment attachment = AttachmentConvertBasic.INSTANCE.dtoToPo(attachmentDTO);
        attachment.setDeleted(DefaultValue.NOT_DELETED);
        Pageable pageable = Page2ResultUtil.buildPageableByParam(currentPage,pageSize,
                Sort.by(Sort.Direction.DESC,"attachId"));
        ExampleMatcher exampleMatcher = ExampleMatcher.matching()
                .withMatcher("contractName",ExampleMatcher.GenericPropertyMatchers.contains())
                .withMatcher("attachName",ExampleMatcher.GenericPropertyMatchers.contains())
                .withMatcher("md5",ExampleMatcher.GenericPropertyMatchers.startsWith())
                .withMatcher("path",ExampleMatcher.GenericPropertyMatchers.startsWith())
                .withMatcher("contentType",ExampleMatcher.GenericPropertyMatchers.startsWith());
        Example<Attachment> attachmentExample = Example.of(attachment,exampleMatcher);
        return attachmentRepository.findAll(attachmentExample,pageable)
                .map(AttachmentConvertBasic.INSTANCE::poToDto);
    }
}
